# debug.py 
#
#  Copyright (c) 2005 Gustavo Sverzut Barbieri
#
#  Author: Gustavo Sverzut Barbieri <barbieri@gmail.com>
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU General Public License as
#  published by the Free Software Foundation; either version 2 of the
#  License, or (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#  USA

import sys
import threading
import traceback
import time


class Output( object ):
    """
    Used by the debug function to output data.
    """

    def write( self, text ):
        """
        Write text.
        """

        sys.stderr.write( text )


    def message_head( self, level ):
        """
        Called before using message()
        """

        if threading.activeCount() > 1:
            self.write( '%s: ' % threading.currentThread().getName() )

    def message_tail( self, level ):
        """
        Called after using message()
        """

        self.write( '\n' )

    def message( self, level,  message ):
        """
        Output message.
        """

        self.write(message)


class XMLOutput(Output):
    def __init__(self):
        self.root_node_out = False

        # keep reference to sys.stderr.write, so we can do the __del__ trick
        self.write = sys.stderr.write

    def __del__(self):
        if self.started():
            self.end()


    def started(self):
        return self.root_node_out


    def start(self):
        self.write('\n<debug>\n')
        self.root_node_out = True


    def end(self):
        self.write('\n</debug>\n')


    def message_head( self, level ):
        if not self.started():
            self.start()

        self.write('\t<debugentry level="%s" timestamp="%s"' % \
            (level, time.time()))

        if threading.activeCount() > 1:
            self.write(' thread="%s"' % threading.currentThread().getName())

        self.write('>\n')


    def message_tail(self, level):
        self.write('\n\t</debugentry>\n')


    def message(self, level, message):
        """
        Output message.
        """

        self.write(message.replace( "<", "&lt;" ).replace( ">", "&gt;" ))

def debug( level, * msgs ):
    debug.lock.acquire()

    try:
        if debug.level >= level:
            out = debug.output
            out.message_head( level )
            msg = out.message

            for m in msgs:
                msg( level, m )

            out.message_tail(level)
    finally:
        debug.lock.release()

debug.level  = 0
debug.lock   = threading.RLock()
debug.output = Output()

try:
    format_exc = traceback.format_exc
except AttributeError:
    # Python < 2.4 doesn't support format_exc(), create it:
    def format_exc( limit=None ):
        return "".join( traceback.format_exception( * sys.exc_info() ) )
    # format_exc()
    traceback.format_exc = format_exc
